﻿using Microsoft.Extensions.Options;
using NewLife.Log;
using NewLife.Net;
using NewLife.Net.Handlers;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;

namespace TK.Socket
{
    /// <summary>
    /// SocketServer
    /// </summary>
    public class SocketServer : ISocketServer
    {
        private readonly int _defaultPort = 65001;
        private readonly SocketConfig _socketConfig;
        private readonly AppServer _appServer;
        private readonly IReceiveDataHandler _receiveData;

        /// <summary>
        /// ctor
        /// </summary>
        public SocketServer(ILog log,
            IOptions<SocketConfig> options,
            IServiceProvider serviceProvider)
        {
            _socketConfig = options.Value;
            _appServer = new AppServer();
            _receiveData = serviceProvider.GetService<IReceiveDataHandler>();
            InitOutputEvent();
            InitLogProvider(log);
            InitConfig();
        }

        /// <summary>
        /// 数据接收
        /// </summary>
        public event Action<DataPacket> ReceiveData;

        /// <summary>
        /// 启用sokcet服务
        /// </summary>
        public Task Start()
        {
            _appServer.Start();
            return Task.CompletedTask;
        }

        /// <summary>
        /// Dispose
        /// </summary>
        public void Dispose()
        {
            try
            {
                _appServer.ReceiveData -= AppServerReceiveData;
                _appServer.DisposeAll();
            }
            catch { }
        }

        #region private methods
        /// <summary>
        /// 初始化socket 配置
        /// </summary>
        private void InitConfig()
        {
            _appServer.LogReceive = _socketConfig.IsReceiveLog;
            _appServer.LogSend = _socketConfig.IsSendLog;
            if (_socketConfig.IPConfigList != null && _socketConfig.IPConfigList.Any())
            {
                foreach (var item in _socketConfig.IPConfigList)
                {
                    var address = IPAddress.Parse(item.IP);
                    var protocolType = item.SocketType == SocketTypeEnum.Tcp ? NetType.Tcp : item.SocketType == SocketTypeEnum.Udp ? NetType.Udp : NetType.Unknown;
                    _appServer.AddServer(address, item.Port, protocolType);
                }
            }
            else
            {
                _appServer.Port = _defaultPort;
            }

            if (_socketConfig.IPConfigList == null || !_socketConfig.IPConfigList.Any()
                || _socketConfig.IPConfigList.Any(m => m.SocketType != SocketTypeEnum.Udp))
            {
                if (_socketConfig.TcpDataProtocol == SocketTcpDataProtocolEnum.LV)
                {
                    var lvcodec = new LengthFieldCodec();
                    if (_socketConfig.TcpLVConfig != null)
                    {
                        _socketConfig.TcpLVConfig.Size = _socketConfig.TcpLVConfig.Size != 1 && _socketConfig.TcpLVConfig.Size != 2 && _socketConfig.TcpLVConfig.Size != 4
                            ? 2 : _socketConfig.TcpLVConfig.Size;
                        _socketConfig.TcpLVConfig.Expire = _socketConfig.TcpLVConfig.Expire <= 500 ? 500 : _socketConfig.TcpLVConfig.Expire;
                        lvcodec.Size = _socketConfig.TcpLVConfig.Size;
                        lvcodec.Offset = _socketConfig.TcpLVConfig.Offset;
                        lvcodec.Expire = _socketConfig.TcpLVConfig.Expire;
                    }

                    _appServer.Add(lvcodec);
                }
                else if (_socketConfig.TcpDataProtocol == SocketTcpDataProtocolEnum.Separator)
                {
                    var separatorCodec = new SplitDataCodec();
                    if (_socketConfig.TcpSeparatorConfig != null)
                    {
                        if (_socketConfig.TcpSeparatorConfig.SplitData != null && _socketConfig.TcpSeparatorConfig.SplitData.Length >= 1)
                        {
                            separatorCodec.SplitData = _socketConfig.TcpSeparatorConfig.SplitData;
                        }

                        if (_socketConfig.TcpSeparatorConfig.MaxCacheDataLength > 1024)
                        {
                            separatorCodec.MaxCacheDataLength = _socketConfig.TcpSeparatorConfig.MaxCacheDataLength;
                        }
                    }

                    _appServer.Add(separatorCodec);
                }
                else if (_socketConfig.TcpDataProtocol != SocketTcpDataProtocolEnum.None)
                {
                    _appServer.Add<LengthFieldCodec>();
                }
            }

            //_appServer.Add(new DataHandler(null));
        }

        /// <summary>
        /// 初始化日志驱动
        /// </summary>
        private void InitLogProvider(ILog log)
        {
            _appServer.Log = log;
            _appServer.SessionLog = log;
            _appServer.SocketLog = log;
        }

        /// <summary>
        /// 初始化数据接收事件
        /// </summary>
        private void InitOutputEvent()
        {
            _appServer.ReceiveData += AppServerReceiveData;
        }

        /// <summary>
        /// 内部数据接收
        /// </summary>
        private void AppServerReceiveData(DataPacket obj)
        {
            if (_receiveData != null)
            {
                _receiveData.ReceiveData(obj);
            }
            else
            {
                ReceiveData?.Invoke(obj);
            }
        }
        #endregion
    }
}
